// ManagerTemplate.h: interface for the ManagerTemplate class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_MANAGERTEMPLATE_H__DBF0A1B2_8FAA_40E8_9D1B_1130AD8805FB__INCLUDED_)
#define AFX_MANAGERTEMPLATE_H__DBF0A1B2_8FAA_40E8_9D1B_1130AD8805FB__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "map.h"
#include "Iterationtemplate.h"
#include "SmartPointer.h"
#include "globalShare.h"

template
<
typename Input,
typename Output
>
BOOL INLINE TypeCast(const Input& i, Output& o)
{
	o = static_cast<Output>(i);
	return TRUE;
}

DllExport BOOL TypeCast<CString, INT>(const CString& i, INT& o);
DllExport BOOL TypeCast<CString, DOUBLE>(const CString &i, DOUBLE& o);
DllExport BOOL TypeCast<CString, LONG>(const CString& i, LONG& o);
DllExport BOOL TypeCast<CString, unsigned long>(const CString& i, unsigned long& o);
DllExport BOOL TypeCast<INT, CString>(const INT& i, CString& o);
DllExport BOOL TypeCast<DOUBLE, CString>(const DOUBLE& i, CString& o);
DllExport BOOL TypeCast<LONG, CString>(const LONG& i, CString& o);
DllExport BOOL TypeCast<unsigned long, CString>(const unsigned long& i, CString& o);

template
<
class ManagedType,
class OutputType, 
class Key, 
class Manager
> 
class ManagerIterator: public IteratorTemplate<OutputType>
{
public:
	ManagerIterator( const Manager* pManager ){
		m_pManager = pManager;
		InitVariable( m_OutPut );
	}
	virtual ~ManagerIterator(){}

public:
	virtual void Begin(){
		m_pos = m_pManager->m_Map.GetStartPosition();
		Next();
	}

	virtual void Next(){
		ManagedType pManaged;
		if(m_pos != m_pManager->m_Map.GetEndPosition() )
		{
			m_pManager->m_Map.GetNextAssoc(m_pos, m_curKey, pManaged);
			TypeCast(pManaged, m_OutPut);
			m_bIsEnd = FALSE;
			return;
		}
		m_bIsEnd = TRUE;
	}
	
	virtual BOOL End() const {
		return m_bIsEnd;
	}
	
	virtual OutputType Get() const {
		return m_OutPut;
	}

	const Key& GetKey() const {
		return m_curKey;
	}
private:
	Key m_curKey;
	BOOL m_bIsEnd;
	OutputType m_OutPut;
	const Manager* m_pManager;
	Manager::Map::Position m_pos;
};

template<class Key, class ManagedType, class OutputType = ManagedType*> 
class ManagerTemplate 
{
public:
	typedef ManagerIterator<ManagedType*, OutputType, Key, ManagerTemplate> Iterator;
	typedef UeSmartPtr<Iterator> IteratorPtr;
	typedef MapFacade< Key, ManagedType* > Map;
	friend Iterator;
public:
	ManagerTemplate(INT nManagerScale = 203){
		m_Map.InitHashTable(nManagerScale);
		m_nElementCount = 0;
		m_nIndex = 0;
	}
	virtual ~ManagerTemplate(){
		DeleteAll();
	}

	ManagedType* GetManaged(const Key key) const {
		ManagedType* Type = 0;
		OutputType otype;
		InitVariable(otype);
		if(m_Map.Lookup(key, Type))
		{
			TypeCast(Type, otype);
			return otype;
		}
		return otype;
	}
	
protected:
	INT GenerateIndex()
	{
		INT nCount = 1;
		while(!GenerateIndex(INT(0), nCount*100000))
		{
			nCount++;
		}
		return m_nIndex;
	}

private:	
	template<typename Type> BOOL GenerateIndex(Type p, INT nMax)
	{
		ASSERT(FALSE);
		return TRUE;
	}

	template<> BOOL GenerateIndex(int p, INT nMax)
	{
		m_nIndex++;
		
		return TRUE;
	}

public:
	INT GetElementCount() const {
		return m_nElementCount;
	}

	Iterator* NewIterator() const {
		return new Iterator(this);
	}

	virtual void DeleteAll(){
		Map::Position pos;
		Key key;
		ManagedType* type = 0;
		pos = m_Map.GetStartPosition();
		while( pos != m_Map.GetEndPosition() )
		{
			m_Map.GetNextAssoc(pos, key, type);
			delete type;
		}
		m_Map.RemoveAll();
		m_nElementCount = 0;
	}

	virtual void DeleteItem(const Key& key){
		ManagedType* Type = 0;
		m_Map.Lookup(key, Type);
		delete Type;
		m_Map.RemoveKey(key);
		m_nElementCount--;
	}

	virtual ManagedType* RemoveItem(const Key& key){
		ManagedType* Type = 0;
		m_Map.Lookup(key, Type);
		m_Map.RemoveKey(key);
		m_nElementCount--;
		return Type;
	}

	BOOL IsExist(const Key key) const {
		ManagedType* Type = 0;
		return m_Map.Lookup(key, Type);
	}

	unsigned long Index() const {
		return m_nIndex;
	}

	void Index(unsigned long nIndex) {
		m_nIndex = nIndex;
	}

	void Add(const Key& key, ManagedType* type){
		ManagedType* Type = 0;
		ASSERT(!m_Map.Lookup(key, Type));
		m_Map.SetAt(key, type);
		m_nElementCount++;
	}
private:
	Map m_Map;
	INT m_nElementCount;
public:
	unsigned long m_nIndex;
};

template
<
typename Key,
typename Value
>
class SameKeyManagerTemplate
{
	private:
		typedef MapEx<Key, Value*> Container_;

	public:
		typedef Container_::Iterator Iterator;
		typedef Container_::IteratorPtr IteratorPtr;

	public:
		SameKeyManagerTemplate(INT nManagerScale = 203){
			m_Map.InitHashTable(nManagerScale);
		}
		virtual ~SameKeyManagerTemplate(){
			DeleteAll();
		}

	public:
		Iterator* GetManaged(const Key& key) {
			return m_Map.Get(key);
		}

		void Add(const Key& key, Value* value ){
			m_Map.Add(key, value);
		}
	public:
		Iterator* NewIterator() const {
			return m_Map.NewIterator();
		}
		
		virtual void DeleteAll(){
			Iterator* pIt = m_Map.NewIterator();
			ASSERT_MEMORY_VALID(pIt, NORETURN);
			for(pIt->Begin(); !pIt->End(); pIt->Next())
			{
				Value* pValue = pIt->Get();
				ASSERT(pValue);
				delete pValue;
			}
			delete pIt;
			m_Map.RemoveAll();
		}
		
		virtual void DeleteItem(const Key& key){
			Iterator* pIt = m_Map.Get(key);
			ASSERT(pIt);
			for(pIt->Begin(); !pIt->End(); pIt->Next())
			{
				Value* pValue = pIt->Get();
				ASSERT(pValue);
				delete pValue;
			}
			delete pIt;

			m_Map.RemoveKey(key);
		}
	private:
		Container_ m_Map;
};

template<typename Key, typename ManagedType, typename OutputType = ManagedType >
class ReferenceManager
{
public:
	typedef ManagerIterator<ManagedType, OutputType, Key, ReferenceManager> Iterator;
	typedef UeSmartPtr<Iterator> IteratorPtr;
	typedef MapFacade< Key, ManagedType > Map;
	friend Iterator;

public:
	ReferenceManager(INT nManagerScale = 203){
		m_Map.InitHashTable(nManagerScale);
		m_nElementCount = 0;
		m_nIndex = 0;
	}

	ReferenceManager( const ReferenceManager& manager ) {
		*this = manager;
	}
	virtual ~ReferenceManager(){}

	BOOL IsExist(const Key key) const {
		ManagedType Type;
		InitVariable(Type);
		return m_Map.Lookup(key, Type);
	}

	void Add(const Key& key, ManagedType type){
		ManagedType Type;
		InitVariable(Type);
		ASSERT(!m_Map.Lookup(key, Type));
		m_Map.SetAt(key, type);
		m_nElementCount++;
	}
	
	OutputType GetManaged(const Key key) const {
		ManagedType Type;
		InitVariable(Type);
		OutputType pOType;
		InitVariable(pOType);
		if(m_Map.Lookup(key, Type))
		{
			TypeCast(Type, pOType);
			return pOType;
		}
		return pOType;
	}
	
	const ReferenceManager& operator=( const ReferenceManager& manager ) {
		if ( this == &manager )
			return *this;
		
		m_Map = manager.m_Map;
		m_nElementCount = manager.m_nElementCount;
		m_nIndex = manager.m_nIndex;
		
		return *this;
	}
	
	const ReferenceManager& operator+=( const ReferenceManager& manager ) {
		if ( this == &manager )
			return *this;
		
		m_Map += manager.m_Map;
		m_nElementCount += manager.m_nElementCount;
		m_nIndex += manager.m_nIndex;
		
		return *this;
	}
	
	ReferenceManager operator+( const ReferenceManager& manager ) const {
		ReferenceManager temp( *this );
		
		temp += manager;
		
		return temp;
	}
protected:
	INT GenerateIndex()
	{
		INT nCount = 1;
		Key* p = NULL;
		while(!GenerateIndex(p, nCount*2048))
		{
			nCount++;
		}
		return m_nIndex;
	}

private:	
	template<typename Type> BOOL GenerateIndex(Type* p, INT nMax)
	{
		ASSERT(FALSE);
		return TRUE;
	}

	template<> BOOL GenerateIndex(int* p, INT nMax)
	{
		OutputType pManaged;
		InitVariable(pManaged);
		int nCount = 1;
		while(nCount <= nMax)
		{
			m_nIndex++;
			if(m_nIndex > nMax)
			{
				m_nIndex = m_nIndex%nMax;
			}
			
			Key key;
			TypeCast(m_nIndex, key);
			pManaged = this->GetManaged(key);
			if(pManaged == NULL)
				return TRUE;
			
			nCount++;
		}
		return FALSE;
	}

public:
	INT GetElementCount() const {
		return m_nElementCount;
	}

	Iterator* NewIterator() const {
		return new Iterator(this);
	}

	virtual void DeleteAll(){
		m_Map.RemoveAll();
		m_nElementCount = 0;
	}

	virtual void DeleteItem(const Key& key){
		m_Map.RemoveKey(key);
	}

private:
	Map m_Map;
	INT m_nElementCount;
private:
	INT m_nIndex;
};
#endif // !defined(AFX_MANAGERTEMPLATE_H__DBF0A1B2_8FAA_40E8_9D1B_1130AD8805FB__INCLUDED_)
